/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package BUS;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
//import java.lang.ProcessBuilder.Redirect.Type;
import java.util.*;
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class IData<T> {
    /**
	 * Hàm khởi tạo
    */
    public IData(){
    }
    public String query = "";
    protected PreparedStatement ps;
    public abstract T add(T item);
   
    /// ham dung de kiem tra truong do da co du lieu hay chua.Neu co chua ve true nguoc lai false
      /**
	 * @param col :Truyền vào tên cột cần kiểm tra
	 * @param value : Giá trị cần kiểm tra
	 * @param  tb_name : Tên bảng kiểm tra
         * @param config :Tên class sẽ thực hiện kết nối với csdl
         * @return : trả về true nếu đã tồn tại. Ngược lại trả về false
    */
    public Boolean Exists(String col,Object value,String tb_name,SubConfig config){
        String mysql = String.format("select %s from %s where %s =?", col,tb_name,col);
        System.out.println("mysql : " + mysql);
        try {
            PreparedStatement cs = config.connec.prepareStatement(mysql);
            cs.setObject(1, value);
            ResultSet rs = cs.executeQuery();
            while(rs.next()){
                return true;
            }
        } catch (SQLException ex) {
            Logger.getLogger(IData.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return false;
    }
    
    protected abstract void add(T item,int t);
      /**
	 * @param list :Truyền vào ds đối tượng .Ví dụ : Users
	 * @param config : Truyền vào class Subconfig thực hiện làm việc với csdl
	 * 
    */
    public  void updateRows(List<T> list,SubConfig config) throws SQLException{
        ps = config.connec.prepareStatement(this.query);
         for(T item : list){
                this.add(item, 1);
         }
         ps.executeBatch();
    }
    
    public abstract void saveBatch();
     /**
	 * @param List<T> :Truyền vào ds đối tượng .Ví dụ : Users
	 * 
	 * 
    */
    public abstract void addrows(List<T> list,SubConfig config);
    public String sWhere = "";
    public abstract T Find(T item,List<T> list);
    /**
	 * @param item :Truyền vào 1 đối tượng .Ví dụ : Users
	 * @param t :Truyền vào giá trị(0,1,2): tương ứng với: 0 là insert,1 là update,2 là delete
	 * @return :Trả về -1 hay 1 hay là id của đối tượng
    */
    protected abstract Object OnSubmit(T item,int t,SubConfig config);
     /**
     * @param item: Truyền vào một đối tượng.Để ghi xuống cơ sở dữ liệu
     * @return : trả về id của dòng vừa được ghi xuống
     */
    public abstract Object insertOnSubmit(T item,SubConfig config);
    /**
     * @param item.Cập nhật lại dòng được sửa tương ứng với đối tượng
     * @return.
     */
    public abstract Object updateOnSubmint(T item,SubConfig config);

    /**
     * @param item.Hàm xóa đi 1 dòng trong cở sở dữ liệu
     * @return
     */
    public abstract Object deleteOnSubmint(T item,SubConfig config);
    
    /**
     * @param rs.Đối số truyền vào 1 dòng dữ liệu
     * @return trả về 1 đối tượng tương ứng với dòng dữ liệu đó.Ví dụ : Users,Historys ...
     */
    protected abstract T getItem(ResultSet rs);
     /**
     * @return.Trả về danh sách các dòng.
     */
    public abstract List<T> getAll(SubConfig config);
    /**
     * @param mySql: truyền vào 1 câu truy vấn hay 1 procedure không có tham số :ví dụ : select * from tableName hay { call GetUsers() }
     * @return :Trả về danh sách các dòng tương ứng với đối tượng cần sử dụng
     */
    public List<T> getAll(String mySql,SubConfig config){
        ResultSet rs;        
    	List<T> list = new ArrayList<T>();    
        try
        {
            Statement st = config.connec.createStatement() ;//kq.createStatement();
            rs = st.executeQuery(mySql);
            while(rs.next()){
            	list.add(getItem(rs));
            }
            rs.close();
            st.close();
        }
        catch(SQLException ex){
        }        
    	return list;
    }
    public List<T> query(String mysql,SubConfig fig,Object ... params){
        List<T> list = new ArrayList<T>();        
        ResultSet rs;		
        PreparedStatement st;
            try {
                st = fig.connec.prepareStatement(mysql);
                for(int i = 0;i < params.length;i++){
                    st.setObject(i+1, params[i]);
                }
                rs = st.executeQuery();
                while(rs.next()){
                     list.add(getItem(rs));
                 }
                 st.close();
                 rs.close();
            } catch (SQLException ex) {
                Logger.getLogger(IData.class.getName()).log(Level.SEVERE, null, ex);
            }            
        return list;
    }
    
    public String ListToJson(String name,List<T> list){        
        Gson g = new Gson();       
        Type listType = new TypeToken<List<T>>() {}.getType();
        String json = g.toJson(list, listType);
        return json;
    }
    
    public Object update(String mysql,SubConfig fig,Object ... params){
        Object result = 0;
        String m = mysql.toLowerCase();
        int t = -1;
        m = m.trim();
        String insert = "insert".toLowerCase();
        if(m.indexOf(insert) > -1){
            t = 0;
        }
        try {
                PreparedStatement cs = fig.connec.prepareStatement(insert);                
                if(t == 0){//lay id vua duoc insert
                    cs = fig.connec.prepareStatement(insert,PreparedStatement.RETURN_GENERATED_KEYS);
                }
                for(int i = 0; i < params.length ;i++){
                    System.out.println("sss " + params[i]);
                    int indexCol = i + 1;
                    cs.setObject(indexCol , params[i]);    
                }                 
                int k = cs.executeUpdate();
                if(t == 0 && k == 1){
                    ResultSet keyResultSet = cs.getGeneratedKeys();
                    if (keyResultSet.next()) {
                        result = (long) keyResultSet.getInt(1);      
                    }
                }
                cs.close();
            }
            catch (SQLException ex) {
                System.out.println("loi :" + ex.getMessage());
                Logger.getLogger(IData.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
}

